首先,要先在電腦的某處建立屬於自己的工作區。未來我們的工作都會在這邊進行。
mkdir rafax
cd rafax
以 composer 建立 composer.json (設定檔)
composer init # 依照自己的想法輸入設定檔,以下作為參考
# Package name (<vendor>/<name>): chivincent/rafax
# Description []: iThome 2018 ironman challenge.
# Author: Vincent Chi <song374561@chivincent.net>
# Minimum Stability []: stable
# Package Type []: project
# License []: MIT
# Would you like to define your dependencies (require) interactively: no
# Would you link to define your dev dependencies (require-dev) interactively: no
composer update # 建立 vendor/autoload.php
# 注意:此時可能會出現 "No locakfile found. Unable to read locked packages"
# 這是因為我們尚未安裝任何 package,故未能產生 composer.lock,忽略即可
至此,你的 composer.json 應該類似於下面的結構
{
"name": "chivincent/rafax",
"description": "iThome 2018 ironman challenge.",
"type": "project",
"license": "MIT",
"authors": [
{
"name": "Vincent Chi",
"email": "song374561@chivincent.net"
}
],
"minimum-stability": "stable",
"require": {}
}
緊接著,我們先建立這個框架第一個程式,依照慣例通常要是 Hello World 。建立 index.php 作為程式的入口點。
// rafax/index.php
<?php
echo 'Hello World'.PHP_EOL;
我們可以啟動 PHP 內置的網頁服務器(Built-in Web Server)來瀏覽其結果
php -S localhost:10000
我們發現,如果連接到 http://localhost:10000/composer.json 即可看到我們專案的 composer.json ,而且可以存取 .git/,這會造成過度的資訊洩露。(儘管現在沒有什麼資訊可以洩露)
一般而言,我們會建立一個獨立的資料夾,用來作為公開的根目錄,在此我們取名為 public ,然後將 index.php 移至 public/ 資料夾下,並且在 public/ 資料夾中重新啟動 PHP 內置網頁伺服器
mkdir public
mv index.php public/
php -S localhost:10000 -t public
為了確保我們未來可以使用 composer 的套件,所以必須在應用程式的入口點(此案例中目前僅有 public/index.php 一個入口點)中優先引入 vendor/autoload.php 。
// rafax/public/index.php
<?php
require __DIR__ . '/../vendor/autoload.php';
echo 'Hello World'.PHP_EOL;
require 而不是 include;為什麼要用 require 而不是 require_oncerequire 會在引入時發生錯誤時(例如被引入目標不存在)拋出 Error 且終止應用程式,但 include 僅會拋出 Warning 且會讓程式繼續向下執行。
對於 composer autoloader 這類無論如何都必須被引入的腳本而言,如果其中發生錯誤應該被提前得知,並且中止應用程式。
composer autoloader 無論在什麼情況下,都應該只被引入一次,以這層意義來看的話其實用 require 或 require_once 都是可以接受的。
然而隨著專案規模的擴大,未來可能會搞不清楚目前位置是否已經引用過 autoload.php ,若一直都是靠著使用 require_once ,因為在執行時期完全沒有任何警告或錯誤,以致於造成冗餘程式碼。
為了避免這樣的情況,當引用 autoload.php 時都建議使用 require ,如果有重複定義時就會由 PHP 直譯器拋出 Fatal error,進而提醒自己避免冗餘程式碼的出現。
__DIR__,而不是使用 dirname(__FILE__)__DIR__ 出現於 PHP 5.3 之後,基本上功能與 dirname(__FILE__) 是完全相同的。
但是這邊要考量一點:__DIR__ 是屬於魔術常數(Magic constants),會在編譯時期(compile-time)被解析,而 dirname(__FILE__) 則是屬於函式呼叫(function-call),是在執行時期(execution-time)被解析。
就以理論角度而言,__DIR__ 的效率應該要比 dirname(__FILE__) 來得高,然而站在編譯器優化的角度來看,其實兩者效率是差不多,甚至是相同的,不過站在程式設計的觀點,它並非一個需要用 function call 解析的路徑,因為 autoload.php 一直都在同一個位置,所以通常是採用 __DIR__ 做路徑的設定。
__DIR__ and dirname(__FILE__) in PHP?